package cn.com.fssg.platform.base.handler.impl.pjqc;

import cn.com.fssg.platform.base.handler.InterfaceHandler;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 评价期次企业结果明细
 */
@Component
public class PjqcQyCountDetail implements InterfaceHandler {

//    private NamedParameterJdbcTemplate jdbcTemplate = BizUtil.cur().tenantMainJdbcTemplate();

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;

    @Override
    public Object run(HttpServletRequest request, JSONObject jsonObject) throws Exception {
        // 评价期次id
        String qcid = jsonObject.get("qcid").toString();
        String sql = "SELECT * FROM bs_pjqc WHERE id=:qcid and pjlb='企业'";
        // 先查询  期次是统计人员还是企业
        HashMap<String, Object> params = new HashMap<>();
        params.put("qcid", qcid);
        List<Map<String, Object>> queryForList = jdbcTemplate.queryForList(sql, params);
        List<Map<String, Object>> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(queryForList)) {
            return result;
        }
        Map<String, Object> pjqc = queryForList.get(0);
        // 评价类别对应企业类型或者人员类型
        String pjff = (String) pjqc.get("pjff");
        // 评价开始和结束时间
        Date pjkssj = (Date) pjqc.get("pjkssj");
        Date pjjssj = (Date) pjqc.get("pjjssj");
        params.put("pjkssj", DateUtil.format(pjkssj, "yyyy-MM-dd HH:mm:ss"));
        params.put("pjjssj", DateUtil.format(pjjssj, "yyyy-MM-dd HH:mm:ss"));
        params.put("pjff", pjff);
        // 企业类别
        if ("设计企业".equals(pjff)) {
            //todo 终审通过 只读取状态记录
            sql = "SELECT DISTINCT ON (dj.id) dj.*, xw.lxmc,qy.zzjgdm,qy.qymc,x.xmmc,x.createname as jsdw,p.bdmc,p.bdhtje,djb.dj AS snddj,djb.bz AS remark," +
                    "(SELECT STRING_AGG(r.role_name,',') FROM v_user u left join v_user_role ur on u.id=ur.user_id left join v_role r on ur.role_id=r.id where dj.createid=u.id and r.id is not null) as role," +
                    "(SELECT count(tb.id) from bs_tbqydj_zb tb where tb.qyid=dj.qyid and tb.tbrq between :pjkssj and :pjjssj) AS tbcs " +
                    "FROM bs_qyxyxwdj dj LEFT JOIN  bs_qydjb djb ON djb.qyid = dj.qyid and djb.nf = to_char(:pjkssj,'yyyy') LEFT JOIN bs_qyjbxx qy ON dj.qyid=qy.id LEFT JOIN bs_xwlx xw ON dj.xwlxid = xw.id left join bs_zcpjdy p on p.id=dj.bdid  left join bs_xzbdfl l on l.id=p.parentid " +
                    "left join bs_xzzbbh h on h.id=l.parentid left join bs_xmzcxx x on x.id=h.parentid WHERE dj.sfzp='0'  " +
                    "and dj.fsrq between :pjkssj and :pjjssj AND dj.bdid not IN (SELECT bcp.bdid FROM bs_pjqc_bcpbd bcp WHERE bcp.parentid=:qcid ) AND qy.qylx=:pjff  ";
        } else {
            //施工企业和监理企业类型
            //todo 终审通过 只读取状态记录
            sql = "SELECT DISTINCT ON (dj.id) dj.*, xw.lxmc,qy.zzjgdm,qy.qymc,x.xmmc,x.createname as jsdw,p.bdmc,p.bdhtje, p.htgclndwcbfb, p.ljwcbfb,djb.dj AS snddj,djb.bz AS remark," +
                    "(SELECT STRING_AGG(r.role_name,',') FROM v_user u left join v_user_role ur on u.id=ur.user_id left join v_role r on ur.role_id=r.id where dj.createid=u.id and r.id is not null) as role," +
                    "(SELECT count(tb.id) from bs_tbqydj_zb tb where tb.qyid=dj.qyid and tb.tbrq between :pjkssj and :pjjssj) AS tbcs, " +
                    "(SELECT STRING_AGG(ry.xm,',') FROM bs_gjrysb sb left join bs_qyryxx ry on sb.qyryid=ry.id where sb.bdid=dj.bdid and sb.bxmcykssj between :pjkssj and :pjjssj and sb.rylx='项目经理' and ry.id is not null) AS xmjl, " +
                    "(SELECT STRING_AGG(ry.xm,',') FROM bs_gjrysb sb left join bs_qyryxx ry on sb.qyryid=ry.id where sb.bdid=dj.bdid and sb.bxmcykssj between :pjkssj and :pjjssj and sb.rylx='项目总工' and ry.id is not null) AS xmzg, " +
                    "(SELECT STRING_AGG(ry.xm,',') FROM bs_gjrysb sb left join bs_qyryxx ry on sb.qyryid=ry.id where sb.bdid=dj.bdid and sb.bxmcykssj between :pjkssj and :pjjssj and sb.rylx='监理工程师' and ry.id is not null) AS jlgcs " +
                    "FROM bs_qyxyxwdj dj LEFT JOIN  bs_qydjb djb ON djb.qyid = dj.qyid and djb.nf = to_char(:pjkssj,'yyyy') LEFT JOIN bs_qyjbxx qy ON dj.qyid=qy.id LEFT JOIN bs_xwlx xw ON dj.xwlxid = xw.id left join bs_zcpjdy p on p.id=dj.bdid  left join bs_xzbdfl l on l.id=p.parentid " +
                    "left join bs_xzzbbh h on h.id=l.parentid left join bs_xmzcxx x on x.id=h.parentid WHERE dj.sfzp='0'  " +
                    "and dj.fsrq between :pjkssj and :pjjssj AND dj.bdid not IN (SELECT bcp.bdid FROM bs_pjqc_bcpbd bcp WHERE bcp.parentid=:qcid ) AND qy.qylx=:pjff  ";

            List<Map<String, Object>> qyxyxwList = jdbcTemplate.queryForList(sql, params);
            if (!CollectionUtils.isEmpty(qyxyxwList)) {
                // 根据企业id分组
                Map<Object, List<Map<String, Object>>> qyCollect = qyxyxwList.parallelStream().collect(Collectors.groupingBy(ry -> ry.get("qyid")));
                for (Map.Entry<Object, List<Map<String, Object>>> qyEntry : qyCollect.entrySet()) {
                    // 投标行为总分
                    double T = 0;
                    // 履约行为总分
                    double L = 0;
                    // 其他行为扣分
                    double J = 0;
                    // 再按行为类型分组
                    Map<String, List<Map<String, Object>>> xwCollect = qyEntry.getValue().stream().collect(Collectors.groupingBy(xw -> (String) xw.get("lxmc")));
                    for (Map.Entry<String, List<Map<String, Object>>> xwEntry : xwCollect.entrySet()) {
                        // 投标行为，履约行为或其他行为
                        String xwlx = xwEntry.getKey();
                        if ("投标行为".equals(xwlx)) {
                            // 进行投标行为得分计算
                            T = 100 - xwEntry.getValue().stream().map(xw -> xw.get("fs"))
                                    .filter(Objects::nonNull)
                                    .mapToDouble(fs -> (Double) fs)
                                    .sum();
                            T = T > 100 ? 100 : T;
                        } else if ("履约行为".equals(xwlx)) {
                            // 按标段进行分组,统计累加
                            Map<String, Double> bdCollect = xwEntry.getValue().stream()
                                    .collect(Collectors.groupingBy(xw -> (String) xw.get("bdid"),
                                            Collectors.summingDouble(xw -> Double.parseDouble(xw.get("fs") == null ? "0" : xw.get("fs").toString()))));
                            // 进行倒排
                            List<Map.Entry<String, Double>> entryList = bdCollect.entrySet().stream()
                                    .sorted(Map.Entry.<String, Double>comparingByValue())
                                    .collect(Collectors.toList());
                            double fm = 0; // 分母
                            double fz = 0; // 分子
                            for (int i = 0; i < entryList.size(); i++) {
                                fm += (i + 1);
                                // 计算每个标段履约行为得分 100-扣分
                                double df = 100 - entryList.get(i).getValue();
                                fz += (i + 1) * (df > 100 ? 100 : df);
                            }
                            L = fz / fm;
                        } else {
                            // 其他扣分或者加分行为,进行累加
                            J = xwEntry.getValue().stream().map(xw -> xw.get("fs")).filter(Objects::nonNull)
                                    .mapToDouble(fs -> (Double) fs)
                                    .sum();

                        }
                    }

                    // 返回的记录行
                    Map<String, Object> qyxyxwItem = qyEntry.getValue().get(0);
                    Map<String, Object> ryRecord = new HashMap<>();
                    // 企业id
                    ryRecord.put("qyid", qyxyxwItem.get("qyid"));
                    // 企业名称
                    ryRecord.put("qymc", qyxyxwItem.get("qymc"));
                    // 企业组织机构代码
                    ryRecord.put("zzjgdm", qyxyxwItem.get("zzjgdm"));
                    // 评价期次id
                    ryRecord.put("qcid", qcid);
                    // 投标行为得分
                    ryRecord.put("tbxwdf", T + "(" + qyxyxwItem.get("tbcs") + ")");
                    // 履约行为得分
                    ryRecord.put("lyxwdf", L);
                    // 最后总得分
                    double fs;
                    if (T == 0 && L != 0) {
                        // 只存在履约行为
                        fs = L - J;
                    } else if (T != 0 && L == 0) {
                        // 只存在投标行为
                        fs = T - J;
                    } else {
                        // 存在履约行为和投标行为
                        fs = 0.1 * T + 0.9 * L - J;
                    }
                    // 最终分数
                    ryRecord.put("fs", String.format("%.2f", fs));
                    // 信用等级
                    ryRecord.put("xydj", getXydj(fs));
                    // 上年度等级
                    ryRecord.put("snddj", qyxyxwItem.get("snddj"));
                    // 备注
                    ryRecord.put("bz", qyxyxwItem.get("remark"));


                    // 再按标段进行分组
                    Map<String, List<Map<String, Object>>> bdCollect = qyEntry.getValue().stream().collect(Collectors.groupingBy(xw -> (String) xw.get("bdid")));
                    // 装载各个标段信息的集合
                    List<Map> bdList = new ArrayList<>();
                    for (Map.Entry<String, List<Map<String, Object>>> bdEntry : bdCollect.entrySet()) {
                        HashMap<String, Object> bd = new HashMap<>();
                        Map<String, Object> bdItem = bdEntry.getValue().get(0);
                        // 标段id
                        bd.put("bdid", bdEntry.getKey());
                        // 项目名称
                        bd.put("xmmc", bdItem.get("xmmc"));
                        // 标段名称
                        bd.put("bdmc", bdItem.get("bdmc"));
                        // 标段合同金额
                        bd.put("bdhtje", bdItem.get("bdhtje"));
                        // 年度完成百分比
                        bd.put("htgclndwcbfb", bdItem.get("htgclndwcbfb"));
                        // 累计完成百分比
                        bd.put("ljwcbfb", bdItem.get("ljwcbfb"));
                        // 建设单位
                        bd.put("jsdw", bdItem.get("jsdw"));
                        // 项目经理
                        bd.put("xmjl", bdItem.get("xmjl"));
                        // 项目总工
                        bd.put("xmzg", bdItem.get("xmzg"));
                        // 项目总监
                        bd.put("jlgcs", bdItem.get("jlgcs"));
                        // 再按行为类型分组(过滤掉投标行为，就只剩履约行为和其他行为)
                        xwCollect = bdEntry.getValue().stream().filter(xw -> !"投标行为".equals(xw.get("lxmc"))).collect(Collectors.groupingBy(xw -> (String) xw.get("lxmc")));
                        double lyxwsjtj = 0; // 履约行为扣分市交通局
                        double lyxwqj = 0; // 履约行为扣分区局
                        double lyxwjsdw = 0; // 履约行为扣分建设单位
                        double qtxwsjtj = 0; // 其他行为扣分市交通局
                        double qtxwqj = 0; // 其他行为扣分区局
                        double qtxwjsdw = 0; // 其他行为扣分建设单位
                        for (Map.Entry<String, List<Map<String, Object>>> xwEntry : xwCollect.entrySet()) {
                            // 履约行为或其他行为
                            String xwlx = xwEntry.getKey();
                            List<Map<String, Object>> xwEntryValue = xwEntry.getValue();
                            // 分别对履约行为和其他行为的每条行为对应的创建人角色进行分数累加
                            if ("履约行为".equals(xwlx)) {
                                for (Map<String, Object> item : xwEntryValue) {
                                    String role = (String) item.get("role");
                                    if (role.contains("市交通局")) {
                                        lyxwsjtj += (Double) item.get("fs");
                                    } else if (role.contains("区局/市直建设单位")) {
                                        lyxwqj += (Double) item.get("fs");
                                    } else if (role.contains("项目建设单位")) {
                                        lyxwjsdw += (Double) item.get("fs");
                                    }
                                }
                            } else {
                                for (Map<String, Object> item : xwEntryValue) {
                                    String role = (String) item.get("role");
                                    if (role.contains("市交通局")) {
                                        qtxwsjtj += (Double) item.get("fs");
                                    } else if (role.contains("区局/市直建设单位")) {
                                        qtxwqj += (Double) item.get("fs");
                                    } else if (role.contains("项目建设单位")) {
                                        qtxwjsdw += (Double) item.get("fs");
                                    }
                                }
                            }
                        }
                        // 履约行为市交通局扣分
                        bd.put("lyxwsjtj", lyxwsjtj);
                        // 履约行为区局扣分
                        bd.put("lyxwqj", lyxwqj);
                        // 履约行为建设单位扣分
                        bd.put("lyxwjsdw", lyxwjsdw);
                        // 其他行为区局扣分
                        bd.put("qtxwqj", qtxwqj);
                        // 其他行为建设单位扣分
                        bd.put("qtxwjsdw", qtxwjsdw);
                        // 其他行为市交通局扣分
                        bd.put("qtxwsjtj", qtxwsjtj);
                        bdList.add(bd);
                    }
                    ryRecord.put("bdList", bdList);
                    result.add(ryRecord);
                }
            }
        }

        return result;
    }

    /**
     * 获取信用等级
     * @param fs 分数
     * @return 信用等级
     */
    private String getXydj(double fs) {
        if (fs >= 95) {
            return "AA";
        } else if (fs >= 85) {
            return "A";
        } else if (fs >= 75) {
            return "B";
        } else if (fs >= 60) {
            return "C";
        } else {
            return "D";
        }
    }

}
